package org.moonlight.jvm.instructions.references.array;

import org.moonlight.jvm.instructions.base.Index16Instruction;
import org.moonlight.jvm.rtda.exclusive.Frame;
import org.moonlight.jvm.rtda.exclusive.OperandStack;
import org.moonlight.jvm.rtda.share.Object;
import org.moonlight.jvm.rtda.share.heap.Class;
import org.moonlight.jvm.rtda.share.heap.symref.ClassRef;
import org.moonlight.jvm.rtda.share.methodarea.RtConstantPool;

/**
 * a_new_array指令: 用来创建引用类型数组。
 *                 它也需要两个操作数:
 *                   1. 第一个操作数是uint16索引，来自字节码。
 *                      通过这个索引可以从当前类的运行时常量池中找到一个类符号引用，
 *                      解析这个符号引用就可以得到数组元素的类。
 *                   2. 第二个操作数是数组长度，从操作数栈中弹出。
 *
 * @author Moonlight
 * @createTime 2023/9/13 14:13
 **/
public class ANewArray extends Index16Instruction {

    @Override
    public void execute(Frame frame) {
        // 当前运行时常量池
        RtConstantPool rtCp = frame.getMethod().getClazz().getRtCp();
        // 数组元素的类的符号引用
        ClassRef classRef = (ClassRef) rtCp.getConstant(this.idx);
        // 数组元素的类
        Class resolvedClass = classRef.resolvedClass();
        // 数组长度
        OperandStack stack = frame.getOperandStack();
        int count = stack.popInt();
        if (count < 0) {
            throw new NegativeArraySizeException();
        }
        Class arrClass = resolvedClass.arrayClass();
        Object array = arrClass.newArray(count);
        stack.pushRef(array);
    }

}
